package com.example.podcaster.services;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.UnknownHostException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.example.podcaster.services.DownloadTask.State;

public class DownloadThread implements Runnable
{
    private final DownloadTask downloadTask;

    private final IDownloadHandler downloadHandler;
    
    private static final int MAX_TRY = 5;
    private static final int SLEEPTIME = 1000;
    
    private int iTry = 0;

    public DownloadThread(DownloadTask downloadTask, IDownloadHandler downloadPermissionChecker)
    {
        this.downloadTask = downloadTask;
        this.downloadHandler = downloadPermissionChecker;
    }

    @Override
    public void run()
    {
        downloadTask.download();

        if (downloadTask.isTerminated())
        {
            downloadHandler.downloadStopped(downloadTask.getId());
            return;
        }
        InputStream input = null;
        RandomAccessFile file = null;
        HttpURLConnection connection = null;
        try
        {
            connection = (HttpURLConnection) downloadTask.getUrl().openConnection();
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)");
            connection.setRequestMethod("GET");

            long total = -1;
            long downloaded = 0;

            if (downloadTask.getFile().exists())
            {
                connection.setRequestProperty("Range", "bytes=" + downloadTask.getFile().length() + "-");
            }
            else
            {
                downloadTask.getFile().createNewFile();
            }
            file = new RandomAccessFile(downloadTask.getFile(), "rw");

            connection.connect();

            System.out.println(connection.getResponseCode());
            if (connection.getResponseCode() == 416)
            {
                file.setLength(0);
                downloadTask.pause();
            }
            else if (connection.getResponseCode() / 100 == 2)
            {
                if (null != connection.getHeaderField("Content-Range"))
                {
                    String range = connection.getHeaderField("Content-Range");

                    String sDownloaded = regSubString(range, "\\d*-");
                    try
                    {
                        downloaded = Integer.valueOf(sDownloaded.substring(0, sDownloaded.length() - 1));
                    }
                    catch (NumberFormatException e)
                    {
                    }

                    String sTotal = regSubString(range, "/\\d*");
                    try
                    {
                        total = Integer.valueOf(sTotal.substring(1, sTotal.length()));
                    }
                    catch (NumberFormatException e)
                    {
                    }
                }
                else
                {
                    total = connection.getContentLength();
                }
                file.seek(downloaded);

                input = new BufferedInputStream(connection.getInputStream());
                byte data[] = new byte[1024];

                int length = -1;
                while ((length = input.read(data)) != -1 && !Thread.currentThread().isInterrupted() && downloadTask.isDownloading() && !downloadTask.isTerminated() && downloaded < total)
                {
                	iTry = 0;
                    downloaded += length;
                    file.write(data, 0, length);
                    downloadTask.setDownloadedSize(downloaded);
                    downloadTask.setTotalSize(total);
                }

                if (downloaded == total)
                {
                    downloadTask.complete();
                }
                else if (downloadTask.getState() == State.DOWNLOADING)
                {
                	downloadTask.pause();
                }
            }
            else
            {
                downloadTask.error();
                downloadHandler.downloadStopped(downloadTask.getId());
            }
        }
        catch (UnknownHostException e)
        {
            downloadTask.pause();
        }
        catch (IOException e)
        {
            downloadTask.pause();
            ++iTry;
            if (iTry == MAX_TRY)
            {
            	downloadTask.error();
            }
        }
        finally
        {
            if (null != input)
            {
                try
                {
                    input.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            if (null != file)
            {
                try
                {
                    file.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            if (null != connection)
            {
                connection.disconnect();
            }
        }
        downloadHandler.downloadStopped(downloadTask.getId());
    }

    private static String regSubString(String s, String regex)
    {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(s);
        if (matcher.find())
        {
            return matcher.group(0);
        }

        return null;
    }
}
